﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;

namespace fess.RPG
{
  struct Answer
  {
    public string text;
    public Action action;

    public Answer(string text, Action action)
    {
      this.text = text;
      this.action = action;
    }
  }

  class Dialog : IActive
  {
    public struct Line
    {
      public ActionCharacter speaker;
      public string message;
      public Answer[] answers;
      public Texture2D picture;

      public Line(ActionCharacter speaker, string message, params Answer[] answers)
      {
        this.speaker = speaker;
        this.message = message;
        this.answers = answers;
        picture = null;
      }

      public Line(ActionCharacter speaker, string message, Texture2D picture)
      {
        this.speaker = speaker;
        this.message = message;
        this.answers = new Answer[0];
        this.picture = picture;
      }
    }

    Queue<Line> dialog = new Queue<Line>();
    ActionCharacter character;
    TimeSpan nextLine;
    FollowAI ai;
    Action after, onEscape;
    bool cancel = false;

    public Dialog(ActionCharacter character, Action after, Action onEscape, params Line[] lines)
    {
      this.character = character;
      this.after = after;
      this.onEscape = onEscape;
      ai = new FollowAI(character, character.Map.game.fess);
      ai.CloseDist = 70;
      ai.FarDist = 90;
      character.AddAI(ai);

      foreach (var l in lines)
        dialog.Enqueue(l);

      nextLine = character.Map.game.time;
    }

    public bool Update(TimeSpan time)
    {
      bool far = (character.Character.Position - character.Map.game.fess.Character.Position).Length() > 110;
      if (cancel || far || dialog.Count == 0 && nextLine <= time)
      {
        ai.stop = true;

        if (dialog.Count == 0 && (nextLine - time < TimeSpan.FromMinutes(1)))
        {
          if (after != null)
            after();
        }
        else if (onEscape != null)
          onEscape();

        return false;
      }

      if (nextLine <= time)
      {       
        var line = dialog.Dequeue();
        var lineTime = line.message.Count(c => c == '\n') * 3 + 5;
        nextLine = time + TimeSpan.FromSeconds(lineTime - 0.2);
        if (line.picture == null)
          if (line.answers.Length == 0)
            line.speaker.Say(line.message, 0, lineTime);
          else
          {
            nextLine = time + TimeSpan.FromDays(1);
            line.speaker.SayWithAnswers(line.message, 0, line.answers);
          }
        else
          line.speaker.GirlSay(line.message, line.picture, 0);

        var fess = character.Map.game.fess;
        line.speaker.Character.Direction = (line.speaker == fess ? character : fess).Character.Position - line.speaker.Character.Position;
      }

      return true;
    }

    public void Skip()
    {
      nextLine = character.Map.game.time;
      character.Map.InvokeDropMessages();
      Update(character.Map.game.time);
    }

    public void Cancel()
    {
      cancel = true;
      character.Map.InvokeDropMessages();
    }
  }
}
